package com.example.speedwaymanager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Random;

import android.util.Log;

public class CCoach {

	private static final int kTechnicalSubPoints = 6;
	private static final String TAG = "CCoach";
	
	private String _name;
	private CTeam _myTeam;
	private ArrayList<CRider> _tacticalAvailableSenior = new ArrayList<CRider>();
	private ArrayList<CRider> _tacticalAvailableJunior = new ArrayList<CRider>();

	public CCoach(CTeam team) {
		_myTeam = team;
	}

	public void createSquad() {
		if (_myTeam.get_homeTeam()) {
			createHomeSquad();
		} else {
			createAwaySquad();
		}
		for (CRider rider : _myTeam.get_squad()) {
			_tacticalAvailableSenior.add(rider);
		}
	}

	/**
	 * generates match squad
	 */
	private void squad() {

		Random generator = new Random(System.currentTimeMillis());
		Collections.reverse(_myTeam.get_seniorRiders());
		Collections.reverse(_myTeam.get_juniorRiders());

		ArrayList<CRider> _seniors123 = new ArrayList<CRider>();
		_seniors123.add(_myTeam.get_seniorRiders().get(0));
		_seniors123.add(_myTeam.get_seniorRiders().get(1));
		_seniors123.add(_myTeam.get_seniorRiders().get(2));

		ArrayList<CRider> _seniors45 = new ArrayList<CRider>();
		_seniors45.add(_myTeam.get_seniorRiders().get(3));
		_seniors45.add(_myTeam.get_seniorRiders().get(4));

		ArrayList<CRider> _juniors67 = new ArrayList<CRider>();
		_juniors67.add(_myTeam.get_juniorRiders().get(0));
		_juniors67.add(_myTeam.get_juniorRiders().get(1));

		Collections.shuffle(_seniors123, generator);
		Collections.shuffle(_seniors45, generator);
		Collections.shuffle(_juniors67, generator);

		_myTeam.get_squad().clear();
		_myTeam.get_squad().add(_seniors123.get(0));
		_myTeam.get_squad().add(_seniors45.get(0));
		_myTeam.get_squad().add(_seniors123.get(1));
		_myTeam.get_squad().add(_seniors45.get(1));
		_myTeam.get_squad().add(_seniors123.get(2));
		_myTeam.get_squad().add(_juniors67.get(0));
		_myTeam.get_squad().add(_juniors67.get(1));

	}

	/**
	 * sets home squad based on home avg
	 */
	private void createHomeSquad() {
		Collections.sort(_myTeam.get_seniorRiders(), new ridersAvgHomeComparator());
		Collections.sort(_myTeam.get_juniorRiders(), new ridersAvgHomeComparator());
		squad();
	}

	private void createAwaySquad() {
		Collections.sort(_myTeam.get_seniorRiders(), new ridersAvgAwayComparator());
		Collections.sort(_myTeam.get_juniorRiders(), new ridersAvgAwayComparator());
		squad();
	}

	private void sortTacticalAvailable() {
		Collections.sort(_tacticalAvailableJunior, new matchAvgsComparator()); // TODO
																				// decide
																				// heatavg
																				// or
																				// points?
		Collections.reverse(_tacticalAvailableJunior);
		Collections.sort(_tacticalAvailableSenior, new matchAvgsComparator()); // TODO
																				// decide
																				// heatavg
																				// or
																				// points?
		Collections.reverse(_tacticalAvailableSenior);
	}

	/**
	 * check if the sub is allowed and coach should sub rider
	 * 
	 * @param heatNumber
	 * @param match
	 */
	public void analyzeChangeRequest(int heat, CMatch match) {
		if (match.isTacticalAllowedCPU()) {
			updateTacticalList(heat, match);
			sortTacticalAvailable();
			CTeam otherTeam = getOtherTeam(match.get_teams());
			int diff = (_myTeam.get_points() - otherTeam.get_points());
			// tactical substitution
			if (diff < -5) {
				ArrayList<CRider> riders = match.get_heats().get(heat).get_ridersOfTeam(_myTeam);
				for (CRider rider : riders) {
					if (canBeReplacedBySenior(rider) && shouldBeReplaced(rider, heat, match)) {
						match.get_heats().get(heat)
								.changeRiders(_tacticalAvailableSenior.get(0), rider);
						CUtils.changeGatesInHeat(match,heat,_tacticalAvailableSenior.get(0), rider);
						_tacticalAvailableSenior.get(0).get_matchStats().set_tacticalAllowed(false);
						updateTacticalList(heat, match);
					}
				}
			}
		}
	}


	private void updateTacticalList(int heat, CMatch match) {
		_tacticalAvailableSenior.clear();
		_tacticalAvailableSenior = (ArrayList<CRider>) _myTeam.get_squad().clone();
		ArrayList<CRider> heatRiders = match.getRidersOfTeamInHeat(heat, _myTeam);
		for (CRider heatRider : heatRiders) {
			_tacticalAvailableSenior.remove(heatRider);
		}
		Iterator<CRider> it = _tacticalAvailableSenior.iterator();
		while (it.hasNext()) {
			CRider rider = it.next();
			if (false == rider.get_matchStats().get_tacticalAllowed()) {
				it.remove();
			}
		}
		
		Log.d(TAG,"_tacticalAvailableSenior");
		for (CRider rider: _tacticalAvailableSenior) {		
			Log.d(TAG,rider.get_numberAndNameAndStats());
		}
	}

	private Boolean canBeReplacedByJunior(CRider rider) {
		if (rider.get_type() == ERiderType.eSenior) {
			return true;
		} else
			return false;
	}

	private Boolean canBeReplacedBySenior(CRider rider) {
		if (rider.get_type() == ERiderType.eJunior) {
			return false;
		} else
			return true;
	}

	private Boolean shouldBeReplaced(CRider rider, int heat, CMatch match) {
		if (rider.get_matchAvg() < _tacticalAvailableSenior.get(0).get_matchAvg()
				&& rider.get_matchStats().get_pointsAndBonuses() < 3) // TODO if
																		// avg
																		// is
																		// better
																		// then
																		// ride
																		// is
																		// for
																		// now
																		// to be
																		// parametrized
		{
			return true;
		} else {
			return false;
		}
	}

	private CTeam getOtherTeam(ArrayList<CTeam> teams) {
		// yes pointers relation. Checking if this is the same object
		if (teams.get(0) == _myTeam) {
			return teams.get(1);
		} else {
			return teams.get(0);
		}
	}
	
	public void setSquad(Object[] sArray) {	
		ArrayList<CRider> squad = new ArrayList<CRider>(); 
		for(Object rider: sArray)
		{
			CRider newRider = (CRider) rider;
			squad.add(newRider);
		}
		_myTeam.set_squad(squad);				
	}
}

	

final class ridersPointsComparator implements Comparator<CRider> {
	@Override
	public int compare(CRider r1, CRider r2) {
		return r1.get_matchStats().get_points().compareTo(r2.get_matchStats().get_points());
	}
}

final class ridersComparator implements Comparator<CRider> {
	@Override
	public int compare(CRider r1, CRider r2) {
		return r1.get_matchStats().get_points().compareTo(r2.get_matchStats().get_points());
	}
}

final class matchAvgsComparator implements Comparator<CRider> {
	@Override
	public int compare(CRider r1, CRider r2) {
		return r1.get_matchAvg().compareTo(r2.get_matchAvg());
	}
}
